﻿using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using pub.CmdUI;
using pub.CmdUI.Cmd;
using pub.GUI.Dialog;
using pub.Interop;
using pub.Types;
using todo.Model;
using todo.Plugin;

namespace todo
{
    public class App
    {
        public static readonly string Title;
        public static readonly string Version;
        public static readonly string locale;

        public static readonly string TempNewFile = "Untitled";

        public static TodoList TodoList { get; set; }
        public static string TodoListFile { get; set; }

        private static bool _dirty;

        public static bool Dirty
        {
            get { return _dirty; }
            set
            {
                if (_dirty == value)
                {
                    return;
                }
                _dirty = value;
                FireDirtyChanged(EventArgs.Empty);
            }
        }

        public static event EventHandler DirtyChanged;

        private static void FireDirtyChanged(EventArgs e)
        {
            var handler = DirtyChanged;
            if (handler != null) handler(null, e);
        }

        public static AppSettings Settings { get; set; }

        //
        public static FrmMain MainForm { get; set; }
        public static int MainThreadId;

        //
        public static CmdUIManager CmdUIManager { get; set; }

        public static AppCmds Cmds
        {
            get { return _appCmds; }
        }

        public static AppCmds _appCmds;

        public static int IdleCount { get; set; }

        public static bool IsFirstInstance { get; set; }

        public static void Initialize()
        {
            //
            var testFile = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "todo.EXE.flag");
            if(!File.Exists(testFile) || Win32.DeleteFile(testFile))
            {
                IsFirstInstance = true;
            }
            var hTestFile = Win32.CreateFile(testFile, 0x80000000, 0x00000001 | 0x00000002, 
                IntPtr.Zero,  4, 0x100, IntPtr.Zero);
            Debug.Assert(hTestFile != Win32.InvalidHandleValue);
//            IsFirstInstance = false;// Marshal.GetLastWin32Error() != Win32.ERROR_ALREADY_EXISTS;
//            MessageBox.Show("@@" + IsFirstInstance);

            //
            Settings = new AppSettings();
            CmdUIManager = new CmdUIManager();

            CmdUIManager.Bind(new DefaultCmd {
                    Shortcut = new CmdShortcut(Keys.Control | Keys.Q),
                    OnExecute = cmd => { Console.WriteLine(".."); }
            });

            _appCmds = new AppCmds();

            Application.Idle += (sender, args) => { ++IdleCount; };

            PluginManager.Instance.Initialize();

            MainThreadId = Thread.CurrentThread.ManagedThreadId;
        }

        static App()
        {
            var assembly = Assembly.GetExecutingAssembly();

            var attributes = assembly.GetCustomAttributes(typeof (AssemblyTitleAttribute), false);
            var titleAttribute = (AssemblyTitleAttribute) attributes[0];
            Title = titleAttribute.Title;

            Version = assembly.GetName().Version.ToString();

#if zh
            locale = "zh";

            InputBox.OkText = "确定(&O)";
            InputBox.CancelText = "取消(&C)";
#else
            locale = "en";
#endif

        }

        public static void NotifyStarted()
        {
            if (Settings["App"]["SuppressCheckFileAssociation"].GetValue(0) != 1)
            {
                new AppRegistrar().CheckRegistered();
            }
        }

        public static void NewTodoList()
        {
            TodoListFile = TempNewFile;
            TodoList = new TodoList();
        }

        public static string Path
        {
            get
            {
                var exeFile = Assembly.GetExecutingAssembly().Location;
                return System.IO.Path.GetDirectoryName(exeFile);
            }
        }

        public static string DataPath
        {
            get
            {
                var path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
                path = System.IO.Path.Combine(path, Title);
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
                return path;
            }
        }

        public static void ShowHelp()
        {
            var chmFile = System.IO.Path.Combine(Path, "todo.en.chm");
            if (!File.Exists(chmFile))
            {
                chmFile = System.IO.Path.Combine(Path, "todo.cn.chm");
            }
            if (!File.Exists(chmFile))
            {
                chmFile = System.IO.Path.Combine(Path, "todo.chm");
            }
            if (!File.Exists(chmFile))
            {
                var msg = "todo.chm not found";
                var title = "Failed to show help";
#if zh
                msg = "未找到todo.chm";
                title = "无法显示帮助";
#endif
                MessageBox.Show(msg, title, MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                Process.Start(chmFile);
            }
        }

        public static void OnUnknownException(Exception e)
        {
            if(e is AbortException)
            {
                return;
            }
            MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
}